﻿// Project: Salient
// http://salient.codeplex.com
// 
// Copyright 2010, Sky Sanders <sky at skysanders.net>
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://salient.codeplex.com/license
// 
// Date: April 24 2010 

#region

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel.Description;
using System.Xml;

#endregion

namespace Salient.ServiceModel
{
    /// <summary>
    /// TODO: extend this class accept a 'settings' type to configure the DataContractSerializer
    /// </summary>
    public class PreserveReferencesOperationBehavior :
        DataContractSerializerOperationBehavior
    {
        #region Ctor

        ///<summary>
        ///</summary>
        ///<param name="operationDescription"></param>
        public PreserveReferencesOperationBehavior(
            OperationDescription operationDescription)
            : base(operationDescription)
        {
        }

        #endregion

        #region Public Methods

        ///// <summary>
        ///// Creates an instance of a class that inherits from <see cref="T:System.Runtime.Serialization.XmlObjectSerializer"/> for serialization and deserialization operations.
        ///// </summary>
        ///// <returns>
        ///// An instance of a class that inherits from the <see cref="T:System.Runtime.Serialization.XmlObjectSerializer"/> class.
        ///// </returns>
        ///// <param name="type">The <see cref="T:System.Type"/> to create the serializer for.</param><param name="name">The name of the generated type.</param><param name="ns">The namespace of the generated type.</param><param name="knownTypes">An <see cref="T:System.Collections.Generic.IList`1"/> of <see cref="T:System.Type"/> that contains known types.</param>
        //public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
        //{
        //    return CreateDataContractSerializer(type, name, ns, knownTypes);
        //}

        ///// <summary>
        ///// Creates an instance of a class that inherits from <see cref="T:System.Runtime.Serialization.XmlObjectSerializer"/> for serialization and deserialization operations with an <see cref="T:System.Xml.XmlDictionaryString"/> that contains the namespace.
        ///// </summary>
        ///// <returns>
        ///// An instance of a class that inherits from the <see cref="T:System.Runtime.Serialization.XmlObjectSerializer"/> class.
        ///// </returns>
        ///// <param name="type">The type to serialize or deserialize.</param><param name="name">The name of the serialized type.</param>
        ///// <param name="ns">An <see cref="T:System.Xml.XmlDictionaryString"/> that contains the namespace of the serialized type.</param>
        ///// <param name="knownTypes">An <see cref="T:System.Collections.Generic.IList`1"/> of <see cref="T:System.Type"/> that contains known types.</param>
        //public override XmlObjectSerializer CreateSerializer(Type type,XmlDictionaryString name, XmlDictionaryString ns,IList<Type> knownTypes)
        //{
        //    return new DataContractSerializer(type, name, ns, knownTypes,
        //                                      2147483646 /*maxItemsInObjectGraph*/,
        //                                      false /*ignoreExtensionDataObject*/,
        //                                      true /*preserveObjectReferences*/,
        //                                      null /*dataContractSurrogate*/);
        //}


        /// <summary>
        /// Creates an instance of a class that inherits from <see cref="T:System.Runtime.Serialization.XmlObjectSerializer"/> for serialization and deserialization operations.
        /// </summary>
        /// <returns>
        /// An instance of a class that inherits from the <see cref="T:System.Runtime.Serialization.XmlObjectSerializer"/> class.
        /// </returns>
        /// <param name="type">The <see cref="T:System.Type"/> to create the serializer for.</param>
        /// <param name="name">The name of the generated type.</param>
        /// <param name="ns">The namespace of the generated type.</param>
        /// <param name="knownTypes">An <see cref="T:System.Collections.Generic.IList`1"/> of <see cref="T:System.Type"/> that contains known types.</param>
        public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
        {
            return new DataContractSerializer(type, name, ns, knownTypes, this.MaxItemsInObjectGraph, this.IgnoreExtensionDataObject, true, this.DataContractSurrogate);
        }

        /// <summary>
        /// Creates an instance of a class that inherits from <see cref="T:System.Runtime.Serialization.XmlObjectSerializer"/> for serialization and deserialization operations with an <see cref="T:System.Xml.XmlDictionaryString"/> that contains the namespace.
        /// </summary>
        /// <returns>
        /// An instance of a class that inherits from the <see cref="T:System.Runtime.Serialization.XmlObjectSerializer"/> class.
        /// </returns>
        /// <param name="type">The type to serialize or deserialize.</param>
        /// <param name="name">The name of the serialized type.</param>
        /// <param name="ns">An <see cref="T:System.Xml.XmlDictionaryString"/> that contains the namespace of the serialized type.</param>
        /// <param name="knownTypes">An <see cref="T:System.Collections.Generic.IList`1"/> of <see cref="T:System.Type"/> that contains known types.</param>
        public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
        {
            return new DataContractSerializer(type, name, ns, knownTypes,
                                              2147483646 /*maxItemsInObjectGraph*/,
                                              false /*ignoreExtensionDataObject*/,
                                              true /*preserveObjectReferences*/,
                                              null /*dataContractSurrogate*/);
            // TODO:URGENT: update tests and samples to specify a binding with the appropriate values, as above, but in configuration and then use the statement below
            // return new DataContractSerializer(type, name, ns, knownTypes, this.MaxItemsInObjectGraph, this.IgnoreExtensionDataObject, true, this.DataContractSurrogate);
            //http://blogs.msdn.com/drnick/archive/2007/05/15/replacing-the-serializer-part-1.aspx
            //http://blogs.msdn.com/drnick/archive/2007/05/18/replacing-the-serializer-part-2.aspx
        }
        #endregion

        #region Private Methods

        ///// <summary>
        ///// BUG:? 
        ///// </summary>
        ///// <param name="type"></param>
        ///// <param name="name"></param>
        ///// <param name="ns"></param>
        ///// <param name="knownTypes"></param>
        ///// <returns></returns>
        ///// http://blogs.msdn.com/drnick/archive/2007/05/15/replacing-the-serializer-part-1.aspx
        //private static XmlObjectSerializer CreateDataContractSerializer(Type type, string name, string ns, IList<Type> knownTypes)
        //{
        //    throw new Exception("THIS IS BROKEN, WILL RECURSE?");
        //    return CreateDataContractSerializer(type, name, ns, knownTypes);
        //}

        #endregion
    }
}